package com.ruoyi.common.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 订单ID生成器（分布式环境安全）
 * 格式：时间戳(13位) + 机器标识(3位) + 序列号(3位) + 随机数(3位) 共22位
 */
public class OrderIdGenerator {
    // 机器标识(2位数字)
    private static final int MACHINE_ID;
    // 序列号(同一秒内自增)
    private static final AtomicInteger SEQUENCE = new AtomicInteger(0);
    // 上次生成ID的时间戳(秒)
    private static long LAST_SECOND = -1L;
    // 序列号最大值
    private static final int MAX_SEQUENCE = 999;

    static {
        // 初始化机器标识
        MACHINE_ID = generateMachineId();
    }

    /**
     * 生成20位唯一订单ID
     */
    public synchronized static String generateOrderId() {
        // 获取当前秒级时间戳(10位)
        long currentSecond = System.currentTimeMillis() / 1000;

        // 处理时钟回拨
        if (currentSecond < LAST_SECOND) {
            throw new RuntimeException("时钟回拨，无法生成订单ID: " + (LAST_SECOND - currentSecond) + "秒");
        }

        // 同一秒内序列号自增
        if (currentSecond == LAST_SECOND) {
            int sequence = SEQUENCE.incrementAndGet();
            if (sequence > MAX_SEQUENCE) {
                // 序列号用尽则等待下一秒
                currentSecond = waitNextSecond(LAST_SECOND);
                SEQUENCE.set(0);
            }
        } else {
            // 新的一秒重置序列号
            SEQUENCE.set(0);
        }

        LAST_SECOND = currentSecond;

        // 生成5位随机数
        int random = ThreadLocalRandom.current().nextInt(100000);

        // 拼接并格式化各部分，确保固定长度
        return String.format("%010d%02d%03d%05d",
                currentSecond,
                MACHINE_ID,
                SEQUENCE.get(),
                random);
    }

    /**
     * 等待到下一秒
     */
    private static long waitNextSecond(long lastSecond) {
        long currentSecond = System.currentTimeMillis() / 1000;
        while (currentSecond <= lastSecond) {
            currentSecond = System.currentTimeMillis() / 1000;
        }
        return currentSecond;
    }

    /**
     * 生成2位机器标识
     */
    private static int generateMachineId() {
        try {
            // 根据IP地址生成机器标识
            InetAddress localHost = InetAddress.getLocalHost();
            String hostAddress = localHost.getHostAddress();
            int hash = hostAddress.hashCode();
            // 确保结果在0-99之间
            return Math.abs(hash % 100);
        } catch (UnknownHostException e) {
            // 异常时使用随机数
            return new Random().nextInt(100);
        }
    }

    // 测试
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            String orderId = generateOrderId();
            System.out.println("订单ID: " + orderId + " 长度: " + orderId.length());
        }
    }
}
    